/**
 * @file ExternClient.java
 * Projet eCOM 2010 (Miage Descartes)
 * @author Doido Sébastien
 * @version 2
 * @brief Définition d'un client lourd (abstract)
 */
package ecom.client;

import ecom.beans.*;
import ecom.shell.ShellRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.transaction.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * @brief Définition du client lourd abstrait
 * @author Doido Sébastien
 */
abstract class ExternClient implements Runnable {

    /**
     * @brief Interface du bean client distant
     */
    @EJB
    private EcomCustomerRemote ecomCustomerBean;
    /**
     * @brief Interface du bean d'administration distant
     */
    @EJB
    private EcomAdminRemote ecomAdminBean;
    /**
     * @brief Interface du programme shell pilotant les beans
     */
    @EJB
    private ShellRemote shell;
    private Context initialContext = null;
    private UserTransaction utx = null;
    private boolean adminMode;

    /**
     * @brief Constructeur du programme client
     * @param adminMode : activation du mode administration si true
     */
    public ExternClient(boolean adminMode) {
        System.out.println("Begining Client...");
        try {
            InitialContext ic;
            ic = new InitialContext();
            utx = (UserTransaction) ic.lookup("UserTransaction");
            ecomCustomerBean = (EcomCustomerRemote) ic.lookup(EcomCustomerRemote.class.getName());
            ecomAdminBean = (EcomAdminRemote) ic.lookup(EcomAdminRemote.class.getName());
            shell = (ShellRemote) ic.lookup(ShellRemote.class.getName());
            this.adminMode = adminMode;
        } catch (NamingException ex) {
            Logger.getLogger("Impossible de creer le contexte : " + ex);
        }
    }

    /**
     * @brief Lancement du programme client
     * @param args : liste d'argument
     * @throws Exception
     */
    public void run() {
        try {
            this.shell.load(ecomCustomerBean, ecomAdminBean, this.adminMode);
            this.shell.executeCommand("output TEXT");
            // Run
            InputStream in = System.in;
            PrintStream out = System.out;
            PrintStream err = System.err;
            boolean stop = false;
            String line = null;
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            out.println(this.shell.getBanner());
            while (!stop) {
                out.print(">");
                try {
                    line = br.readLine();
                } catch (IOException ex) {
                    err.println("Could not read input, please try again.");
                    continue;
                }
                line = line.trim();
                if (line.length() == 0) {
                    continue;
                }
                try {
                    if (line.contains("batch")) {
                        this.batch(line, out, err);
                    } else {
                        out.println(this.shell.executeCommand(line));
                    }
                    out.flush();
                } catch (Exception ex) {
                    err.println("Shell: " + ex);
                }
                if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) {
                    stop = true;
                    return;
                }
            }
        } catch (Exception ex) {
            Logger.getLogger(ExternClient.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * @brief Lancement d'une commande 'batch' pour jeu d'essai du client lourd
     * @param cmdline : commande batch avec arguments
     * @param out : flux d'affichage
     * @param err : flux d'erreur
     * @return l'affichage
     * @throws Exception
     */
    public String batch(String cmdline, PrintStream out, PrintStream err) throws Exception {
        StringTokenizer st = new StringTokenizer(cmdline, " ");
        String filePath = "";
        String line = "";
        boolean stopOnError;
        InputStream in = null;

        // Ignore the command name.
        st.nextToken();

        int sleep = Integer.parseInt(st.nextToken());

        if (st.countTokens() == 1) {
            out.println("  [stopOnError = FALSE]");
            stopOnError = false;
        } else if (st.countTokens() == 2) {
            st.nextToken();
            out.println("  [stopOnError = TRUE]");
            stopOnError =
                    true;
        } else {
            err.println("error nombre args");
            return "";
        }

        filePath = st.nextToken();

        // Test de l'existence fichier (+ acces au fichier)
        try {
            in = new FileInputStream(filePath);

            // Lecture des commandes (+ execution)
            InputStreamReader inReader = new InputStreamReader(in);
            BufferedReader br = new BufferedReader(inReader);

            while ((line = br.readLine()) != null) {
                out.println("\n  [BATCH command] -> " + line + "\n");
                try {

                    if (line.contains("batch")) {
                        this.batch(line, out, err);
                    } else {
                        out.println(this.shell.executeCommand(line));
                        //this.wait(3000);
                    }
                } catch (Exception ex) {
                    if (stopOnError == true) {
                        err.println("Error and stopOnError ON : stop batch execution");
                        err.println(ex);
                        return "";
                    } else {
                        err.println("Shell :" + ex);
                    }
                }
            }
            br.close();
        } catch (FileNotFoundException e) {
            err.println("File \"" + filePath + "\" not found" + e);
        } catch (IOException e) {
            err.println("Error : " + e);
        }
        return "";
    }
}

